package cn.fengLone.pay.util;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.log4j.Logger;

import cn.fengLone.pay.util.RSA.RSAUtil;

import com.alibaba.fastjson.JSONObject;

/**
 * 
 * https POST请求工具类
 * 
 * @compny 深圳风轮科技有限公司
 * 
 * @author Guo PengFei
 * 
 * @date 2017-08-18
 * 
 * @version V1.0
 * 
 */
public class HttpsUtil {

	private static Logger logger = Logger.getLogger(HttpsUtil.class);

	/**
	 * 创建SSLClient
	 * 
	 * @return
	 */
	public static CloseableHttpClient createSSLClientDefault() {
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(
					null, new TrustStrategy() {

						public boolean isTrusted(X509Certificate[] chain,
								String authType) throws CertificateException {
							return true;
						}
					}).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
					sslContext);
			return HttpClients.custom().setSSLSocketFactory(sslsf).build();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		return HttpClients.createDefault();
	}
	 /**
	  * 发送数据
	  * @param order_num 第三方系统的订单号
	  * @param total_amount  总金额
	  * @param payResult  订单结果
	  * @param siteToken  第三方系统站点标志
	  * @param publicKey  支付平台公钥
	  * @param siteUrl    第三方系统的回调URL
	  * @return
	  * @throws Exception
	  */
	public static Integer sendMsgToClient(String order_num, String total_amount,
			char payResult, String siteToken,
			String publicKey, String siteUrl) throws Exception {
		// 异步通知，需要返回给第三方系统通知结果
		Map<String, String> signParaMap = new HashMap<String, String>();
		signParaMap.put("total_amount", total_amount);
		signParaMap.put("order_num", order_num);
		signParaMap.put("return_code", "1");
//		String payR = SimpleUtil.getChinesePayResult(payResult);
		String payR = SimpleUtil.getPayResultDe(payResult);
		signParaMap.put("payResult", payR);

		String sign_value = RSAUtil.encryptByPublicKey(signParaMap, publicKey);
		String site_token = RSAUtil.encryptByPublicKey(siteToken, publicKey);

		Map<String, String> clientParaMap = new HashMap<String, String>();
		clientParaMap.put("siteToken", site_token);
		clientParaMap.put("sign_value", sign_value);
		String backUrl = siteUrl;
		logger.info("-----aliPayAsyncRes send to url：" + backUrl);
		logger.info("-----aliPayAsyncRes send data：" + clientParaMap);
		Map<String, String> sendResultMap = HttpsUtil.httpClientPost(backUrl,
				clientParaMap);
		String responseBody = sendResultMap.get("responseBody");
		Integer result = 1;
		if (responseBody != null) {
			// 通知异常
			JSONObject resultJson = JSONObject.parseObject(responseBody);
			logger.info("order:" + order_num + "send result:" + responseBody);

			if (resultJson.containsKey("return_code")) {
				String return_code = resultJson.getString("return_code");
				if (return_code.equals("01")) {
					// 发送成功
					result = 2;
				} else {
					// 处理过程中出现错误
					result = 3;
				}
			}
		}
		return result;

	}
	/**
	 * get请求
	 * 
	 * @param url
	 * @return
	 */
	public static String requestGet(String url) {
		CloseableHttpClient httpClient = createSSLClientDefault();
		HttpGet get = new HttpGet();
		StringBuffer sb = new StringBuffer();
		try {
			get.setURI(new URI(url));
			HttpResponse response = httpClient.execute(get);
			response.getEntity();
			HttpEntity entity = response.getEntity();
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					entity.getContent(), "UTF-8"));
			String buffer = null;
			while ((buffer = reader.readLine()) != null) {
				sb.append(buffer);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			logger.info("error:" + e.getMessage());
			e.printStackTrace();
		} catch (URISyntaxException e) {
			// TODO Auto-generated catch block
			logger.info("error:" + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.info("error:" + e.getMessage());
			e.printStackTrace();
		} finally {
			logger.info("abort");

			get.abort();
		}
		return sb.toString();
	}

	/**
	 * post 请求
	 * 
	 * @param url
	 * @param jsonObject
	 * @return
	 */
	public static String requestPost(String url, JSONObject jsonObject) {

		CloseableHttpClient httpClient = createSSLClientDefault();
		HttpPost post = new HttpPost();
		StringBuffer sb = new StringBuffer();
		try {
			post.setURI(new URI(url));
			StringEntity entity1 = new StringEntity(jsonObject.toString(),
					"UTF-8");

			post.setEntity(entity1);

			HttpResponse response = httpClient.execute(post);
			HttpEntity entity = response.getEntity();
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					entity.getContent(), "UTF-8"));
			String buffer = null;
			while ((buffer = reader.readLine()) != null) {
				sb.append(buffer);
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			logger.info("error:" + e.getMessage());
			e.printStackTrace();
		} catch (URISyntaxException e) {
			// TODO Auto-generated catch block
			logger.info("error:" + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.info("error:" + e.getMessage());
			e.printStackTrace();
		} finally {
			post.abort();
		}
		return sb.toString();

	}

	/**
	 * 
	 * @param urlStr
	 * @param map
	 * @param encoding
	 * @param address
	 * @param port
	 * @return
	 */
	public static String send(String urlStr, Map<String, String> map,
			String encoding, String address, int port) {
		String body = "";
		StringBuffer sbuf = new StringBuffer();
		if (map != null) {
			for (Entry<String, String> entry : map.entrySet()) {
				sbuf.append(entry.getKey()).append("=")
						.append(entry.getValue()).append("&");
			}
			if (sbuf.length() > 0) {
				sbuf.deleteCharAt(sbuf.length() - 1);
			}
		}
		// 1、重新对请求报文进行 GBK 编码
		byte[] postData = null;
		try {
			postData = sbuf.toString().getBytes(encoding);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			System.out.println("" + e.getMessage());
		}

		// 2、发送 HTTP(S) 请求
		OutputStream reqStream = null;
		InputStream resStream = null;
		URLConnection request = null;
		try {
			System.out.println("交易请求地址：" + urlStr);
			System.out.println("参数：" + sbuf.toString());

			// A、与服务器建立 HTTP(S) 连接
			URL url = null;
			try {
				Proxy proxy = new Proxy(java.net.Proxy.Type.HTTP,
						new InetSocketAddress(address, port));

				url = new URL(urlStr);
				request = url.openConnection(proxy);
				request.setDoInput(true);
				request.setDoOutput(true);
			} catch (MalformedURLException e) {
				e.printStackTrace();
				System.out.println("MalformedURLException【" + e.getMessage()
						+ "】");

			} catch (IOException e) {
				e.printStackTrace();
				System.out.println("IOException【" + e.getMessage() + "】");

			}

			// B、指定报文头【Content-type】、【Content-length】 与 【Keep-alive】
			request.setRequestProperty("Content-type",
					"application/x-www-form-urlencoded");
			request.setRequestProperty("Content-length",
					String.valueOf(postData.length));
			request.setRequestProperty("Keep-alive", "false");
			request.setRequestProperty("User-Agent",
					"Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

			// C、发送报文至服务器
			reqStream = request.getOutputStream();
			reqStream.write(postData);
			reqStream.close();

			// D、接收服务器返回结果
			ByteArrayOutputStream ms = null;
			resStream = request.getInputStream();
			ms = new ByteArrayOutputStream();
			byte[] buf = new byte[4096];
			int count;
			while ((count = resStream.read(buf, 0, buf.length)) > 0) {
				ms.write(buf, 0, count);
			}
			resStream.close();
			body = new String(ms.toByteArray(), encoding);
		} catch (UnknownHostException e) {
			System.out.println("服务器不可达【" + e.getMessage() + "】");
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("IOException【" + e.getMessage() + "】");

		} finally {
			try {
				if (reqStream != null)
					reqStream.close();
				if (resStream != null)
					resStream.close();
			} catch (Exception ex) {
				System.out.println("ex【" + ex.getMessage() + "】");

			}
		}

		System.out.println("交易响应结果：");
		System.out.println("body" + body);
		return body;
	}

	/**
	 * httpclient3.1
	 * 
	 * @param URL
	 * @param paramsMap
	 * @param client
	 * @return
	 */
	public static Map<String, String> httpClientPost(String URL,
			Map<String, String> paramsMap) {
		logger.info("URL:" + URL);
		logger.info("paramsMap:" + paramsMap);

		HttpClient httpClient = new HttpClient();
		httpClient.getHttpConnectionManager().getParams()
				.setConnectionTimeout(30000);
		httpClient.getHttpConnectionManager().getParams().setSoTimeout(5000);
		// 字符集
		httpClient.getParams().setParameter(
				HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF8");
		return executeByPostWithParamsMap(URL, paramsMap, httpClient);
	}

	public static Map<String, String> executeByPostWithParamsMap(String URL,
			Map<String, String> paramsMap, HttpClient client) {
		String responseBody = null;
		PostMethod method = new PostMethod(URL);
		Map<String, String> resultMap = new HashMap<String, String>();
		// 构造参数
		if (paramsMap != null) {
			Set<Entry<String, String>> entrySet = paramsMap.entrySet();
			Iterator<Entry<String, String>> iterator = entrySet.iterator();
			NameValuePair[] nvps = new NameValuePair[paramsMap.size()];
			int i = 0;
			while (iterator.hasNext()) {
				Entry<String, String> entry = iterator.next();
				if (entry.getKey() != null) {
					NameValuePair nvp = new NameValuePair(entry.getKey(),
							entry.getValue());
					nvps[i++] = nvp;
				}
			}
			method.setRequestBody(nvps);
		}
		method.setRequestHeader("Content-type",
				"application/x-www-form-urlencoded; charset=UTF-8");
		// 提交请求
		int resp= 0;
		try {
			resp= client.executeMethod(method);
			logger.info("resp:" + resp);
			if (resp == 200) {
				responseBody = method.getResponseBodyAsString();
			}
			logger.info("responseBody:" + responseBody);

		} catch (Exception e) {
			e.printStackTrace();
			logger.info("Exception:" + e.getMessage());
		} finally {
			method.releaseConnection();
			client.getHttpConnectionManager().closeIdleConnections(0);
			logger.info("out finally end");
		}
		resultMap.put("return_code", String.valueOf(resp));
		resultMap.put("responseBody", responseBody);
		return resultMap;
	}

}
